Accessibility Fundamentals
Accessibility ensures people with diverse abilities can perceive, understand, navigate, and interact with your app. Key areas to address are semantics for UI elements, correct focus order and keyboard navigation, readable content under large text scale, adequate contrast, and support for assistive technologies like screen readers. Treat accessibility as core design work, not an afterthought.
Semantic Widgets and Labels
- Use built-in semantic-aware widgets such as TextButton, IconButton, ListTile, and Text to provide baseline accessibility.
- Add semantic information using the Semantics widget for custom or decorative widgets.
- Use meaningful labels for interactive elements, concise hints for complex controls, and role annotations for groups of controls.
Examples of Semantic Usage
- Provide a
Semantics(label: 'Close', button: true)around a tappable icon that lacks text. - Use
excludeSemanticsto avoid duplicate announcements when wrapping already semantic widgets.
Screen Readers and Dynamic Announcements
- Support TalkBack on Android and VoiceOver on iOS by ensuring widgets expose appropriate semantics.
- Announce important dynamic changes using
SemanticsService.announceto inform screen reader users when content updates asynchronously. - Keep announcements short and specific and avoid redundant or noisy announcements during frequent updates.
Examples
- Announce completion of a long-running task with
SemanticsService.announce('Upload complete', TextDirection.ltr). - When showing error dialogs, ensure focus moves to the dialog and use semantic labels for the close action.
Focus Management and Keyboard Navigation
- Use Focus, FocusScope, and FocusNode to control keyboard and accessibility focus for forms and custom controls.
- Ensure logical focus order that matches visual order and supports tab navigation.
- Provide clear visual focus indicators for keyboard users and avoid traps where focus cannot move away from a modal.
Patterns
- Move focus to the next logical field on form submission with
FocusScope.of(context).requestFocus(nextFocusNode). - When opening a modal, set initial focus into the modal and return focus to the opener when the modal closes.
Text Scaling, Layout, and Contrast
- Respect user text scaling preferences via MediaQuery.textScaleFactor and test layouts at large scale factors to avoid clipping or overlap.
- Use relative sizing from TextTheme and avoid hard-coding font sizes.
- Ensure color contrast meets WCAG guidelines. Use accessible color tokens and test contrast ratios for primary text, icons, and interactive controls.
- Avoid conveying information by color alone; provide text or icon alternatives.
Testing Checklist
- Verify UI at textScaleFactor 1.4 and 2.0.
- Test with high contrast mode and different device font families.
- Validate focus indicators remain visible under scaled text and high contrast.
Touch Targets and Interaction Affordances
- Make interactive touch targets at least 44x44 logical pixels to accommodate diverse motor abilities.
- Provide spacing between tappable controls and avoid dense clusters.
- For gesture-only controls, provide alternative explicit controls or affordances accessible through semantics.
Examples
Wrap small icons with SizedBox of minimum tappable size and use InkWell for ripple and hit testing.
Localization Strategy
- Externalize user-facing strings into ARB or JSON resource files and load them via the intl package or Flutter localization tools.
- Use code generation tools to produce strongly typed localization accessors for safety.
- Localize not only text but also date, number, currency formatting, pluralization, and right-to-left layout where applicable.
Key Steps
- Define messages in English as the source language.
- Add localized ARB files for supported locales.
- Generate localization delegates and wire them into MaterialApp with supportedLocales and localizationsDelegates.
Pluralization, Gender, and Formatting
- Use ICU message syntax or intl helpers for pluralization and gender-sensitive text.
- Format numbers, currencies, and dates with locale-aware APIs.
- Avoid concatenating localized fragments that may produce incorrect grammar in other languages.
Examples
- Use
Intl.plural(count, zero: 'No items', one: '1 item', other: '$count items'). - Use
NumberFormat.currency(locale: localeName)for currency display.
Right-to-Left and Bidirectional Layouts
- Support RTL languages by using Directionality and setting
textDirectionfrom the current locale or MaterialApp automatic handling. - Verify mirrored layouts for icons, padding, and alignment when switching to RTL.
- Test both LTR and RTL flows including navigation, animations, and custom painting.
Practical tip: Avoid hard-coded left/right paddings; prefer EdgeInsetsDirectional and alignment anchors that adapt automatically.
Localizing Images and Assets
- Provide locale-specific assets when text is embedded in images or cultural variants are necessary.
- Use AssetBundle variants or runtime selection based on Locale to pick appropriate images.
- Avoid embedding text in images when possible and prefer overlays so translations remain editable.
Testing Accessibility and Localization
- Test with real assistive technologies on devices: TalkBack and VoiceOver.
- Run automated accessibility checks using semantic tree inspections and accessibility testing tools where available.
- Test localized builds on actual devices or emulators for layout and string overflow issues.
- Include accessibility tests in CI where feasible, such as checking that critical interactive widgets have semantics and labels.
Testing Checklist
- Run manual walkthrough with screen reader and keyboard navigation.
- Verify screen reader reads logical greetings and error messages.
- Verify localized strings load and plural forms render correctly.
Documentation and Developer Practices
- Maintain a localization guide in the repository with instructions for adding locales and translators workflow.
- Keep a glossary of terms and context notes for translators to avoid ambiguity.
- Use continuous localization workflows or translation management systems for scale.
Practices
- Mark translatable strings and supply developer notes for context.
- Keep each ARB file in sync with the base language and automate generation of missing translations reports.
Exercises
1. Accessibility audit
Run an accessibility audit of an existing screen. Add semantics to unlabeled controls, fix focus order, and provide announcements for dynamic content. Document changes and test with a screen reader.
2. Localization implementation
Add a second locale to an app. Externalize strings, implement pluralization, format currency for the locale, and verify layouts for the new language.
3. RTL verification
Create a localized build for an RTL language, switch Directionality at runtime, and fix mirrored layout issues. Provide before and after screenshots.